package org.example.model;

import lombok.Getter;
import lombok.Setter;
import org.example.CommonMsg;
import org.example.MsgConstants;
import org.example.command.OrderCmd;
import org.example.engine.RbCmd;
import org.example.order.MatchEvent;
import org.example.order.OrderStatus;
import org.example.service.MQTTClient;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;

@Getter
public class OrderBucketImpl implements OrderBucket{
    @Getter
    @Setter
    private long price;

    private long volumn;

    private final LinkedHashMap<Long, Order> orders = new LinkedHashMap<>();

    @Autowired
    private MQTTClient mqttClient;

    @Override
    public void put(Order order) {
        orders.put(order.getOrderId(), order);
        volumn += order.getLeftVolumn();
    }

    @Override
    public Order remove(long oid) {
        Order order = orders.get(oid);
        if(order == null) {
            return null;
        }
        orders.remove(oid);
        volumn -= order.getLeftVolumn();
        return order;
    }

    /**
     * S 46 --> 5, 10, 24
     * S 45 --> 11, 20 10 20
     * B 45 100
     * @param volumnWant
     * @param command
     * @param removeOrderCall
     * @return
     */
    @Override
    public long match(long volumnWant, RbCmd command, Consumer<Order> removeOrderCall) {
        Iterator<Map.Entry<Long, Order>> iterator = orders.entrySet().iterator();
        long matched = 0;
        while(iterator.hasNext() && volumnWant > 0) {
            Map.Entry<Long, Order> next = iterator.next();
            Order order = next.getValue();
            long traded = Math.min(volumnWant, order.getLeftVolumn());//成交量
            matched += traded;

            order.addCompletedVolumn(traded);
            this.volumn -= traded;
            volumnWant -= traded;
            boolean isFullMatch = order.isFullMatch();
            genMatchEvent(order, command, isFullMatch,volumnWant==0, traded);
            if(isFullMatch) {
                removeOrderCall.accept(order);
                iterator.remove();
            }
        }

        return matched;
    }

    @Override
    public boolean isEmpty() {
        return this.volumn == 0;
    }

    private void genMatchEvent(Order order, RbCmd command, boolean isFullMatch, boolean cmdFullMatch, long trated) {
        System.out.println("发送撮合消息，暂时没有实现");
        System.out.println(order.toString());
        System.out.println(command.toString());

        long now = System.currentTimeMillis();
        long tid = -1;
        MatchEvent orderEvent = createEvent(now, order.getMid(),
                order.getOrderId(),
                isFullMatch ? OrderStatus.ORDER_ED : OrderStatus.PART_TRADE,
                tid,
                trated,
                price
        );
        command.matchEventList.add(orderEvent);
        MatchEvent cmdEvent = createEvent(now,command.mid,
                command.oid,
                cmdFullMatch ? OrderStatus.ORDER_ED : OrderStatus.PART_TRADE,
                tid,
                trated,
                command.price
        );

        command.matchEventList.add(cmdEvent);
    }


    private MatchEvent createEvent(long timestamp, int mid, long oid, OrderStatus status, long tid, long volume, long price) {
        MatchEvent matchEvent = new MatchEvent();
        matchEvent.timestamp = timestamp;
        matchEvent.mid = mid;
        matchEvent.oid = oid;
        matchEvent.status = status;
        matchEvent.tid = tid;
        matchEvent.volume = volume;
        matchEvent.price = price;
        return matchEvent;
    }
}
